package page

import (
	"context"
	"fmt"
	"time"

	"BookStack/internal/domain/events"
	"BookStack/internal/domain/page"
	appErrors "BookStack/pkg/errors"
	"BookStack/pkg/utils"
)

// Service 自定义页面应用服务接口
type Service interface {
	// CreatePage 创建自定义页面
	CreatePage(ctx context.Context, req *CreatePageRequest, userID uint) (*PageResponse, error)

	// UpdatePage 更新自定义页面
	UpdatePage(ctx context.Context, id uint, req *UpdatePageRequest, userID uint) (*PageResponse, error)

	// DeletePage 删除自定义页面
	DeletePage(ctx context.Context, id uint, userID uint) error

	// GetPageByID 根据ID获取自定义页面
	GetPageByID(ctx context.Context, id uint) (*PageResponse, error)

	// GetPageBySlug 根据Slug获取自定义页面
	GetPageBySlug(ctx context.Context, slug string) (*PageResponse, error)

	// ListPages 获取自定义页面列表
	ListPages(ctx context.Context, params *PageListQueryParams) (*PageListResponse, error)

	// SetPageStatus 设置自定义页面状态
	SetPageStatus(ctx context.Context, id uint, req *SetPageStatusRequest, userID uint) (*PageResponse, error)
}

// service 自定义页面应用服务实现
type service struct {
	pageService    page.Service
	eventPublisher events.Publisher
}

// NewService 创建自定义页面应用服务
func NewService(pageService page.Service, eventPublisher events.Publisher) Service {
	return &service{
		pageService:    pageService,
		eventPublisher: eventPublisher,
	}
}

// CreatePage 创建自定义页面
func (s *service) CreatePage(ctx context.Context, req *CreatePageRequest, userID uint) (*PageResponse, error) {
	// 检查Slug是否已存在
	pageBySlug, err := s.pageService.GetBySlug(ctx, req.Slug)
	if err == nil && pageBySlug != nil {
		return nil, PageSlugExists(req.Slug)
	}

	// 调用领域服务创建页面
	createdPage, err := s.pageService.Create(
		ctx,
		req.Title,
		req.Slug,
		req.Content,
		req.Description,
		req.Status,
		userID,
	)
	if err != nil {
		return nil, WrapError(err)
	}

	// 发布事件
	event := &events.PageCreatedEvent{
		ID:        createdPage.ID,
		Title:     createdPage.Title,
		Slug:      createdPage.Slug,
		Status:    createdPage.Status,
		CreatedBy: userID,
		CreatedAt: utils.TimeToJSONTime(createdPage.CreatedAt),
	}

	// 异步发布事件
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.PageCreatedEventType, event))

	// 转换为响应
	return PageToResponse(createdPage), nil
}

// UpdatePage 更新自定义页面
func (s *service) UpdatePage(ctx context.Context, id uint, req *UpdatePageRequest, userID uint) (*PageResponse, error) {
	// 获取现有页面以检查权限和验证存在性
	existingPage, err := s.pageService.GetByID(ctx, id)
	if err != nil {
		return nil, WrapError(err)
	}

	// 如果slug发生变化，检查新slug是否已存在
	if existingPage.Slug != req.Slug {
		pageBySlug, err := s.pageService.GetBySlug(ctx, req.Slug)
		if err == nil && pageBySlug != nil && pageBySlug.ID != id {
			return nil, PageSlugExists(req.Slug)
		}
	}

	// 调用领域服务更新页面
	updatedPage, err := s.pageService.Update(
		ctx,
		id,
		req.Title,
		req.Slug,
		req.Content,
		req.Description,
		req.Status,
	)
	if err != nil {
		return nil, WrapError(err)
	}

	// 发布事件
	event := &events.PageUpdatedEvent{
		ID:        updatedPage.ID,
		Title:     updatedPage.Title,
		Slug:      updatedPage.Slug,
		Status:    updatedPage.Status,
		UpdatedBy: userID,
		UpdatedAt: utils.TimeToJSONTime(updatedPage.UpdatedAt),
	}

	// 异步发布事件
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.PageUpdatedEventType, event))

	// 转换为响应
	return PageToResponse(updatedPage), nil
}

// DeletePage 删除自定义页面
func (s *service) DeletePage(ctx context.Context, id uint, userID uint) error {
	// 获取现有页面（以确认其存在）
	existingPage, err := s.pageService.GetByID(ctx, id)
	if err != nil {
		return WrapError(err)
	}
	if existingPage == nil {
		return PageNotFound(id)
	}

	// 删除页面
	if err := s.pageService.Delete(ctx, id); err != nil {
		return appErrors.Wrap(err, appErrors.ErrCodeDatabase, "删除页面失败")
	}

	// 发布事件
	event := &events.PageDeletedEvent{
		ID:        existingPage.ID,
		Title:     existingPage.Title,
		Slug:      existingPage.Slug,
		DeletedBy: userID,
		DeletedAt: utils.TimeToJSONTime(time.Now()),
	}

	// 异步发布事件
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.PageDeletedEventType, event))

	return nil
}

// GetPageByID 根据ID获取自定义页面
func (s *service) GetPageByID(ctx context.Context, id uint) (*PageResponse, error) {
	// 获取页面
	page, err := s.pageService.GetByID(ctx, id)
	if err != nil {
		return nil, WrapError(err)
	}
	if page == nil {
		return nil, PageNotFound(id)
	}

	// 增加阅读计数
	if err := s.pageService.IncrementViewCount(ctx, id); err != nil {
		// 增加阅读计数失败不影响返回结果
		fmt.Printf("增加页面阅读计数失败: %v\n", err)
	} else {
		page.ViewCount++
	}

	// 转换为响应
	return PageToResponse(page), nil
}

// GetPageBySlug 根据Slug获取自定义页面
func (s *service) GetPageBySlug(ctx context.Context, slug string) (*PageResponse, error) {
	// 获取页面
	page, err := s.pageService.GetBySlug(ctx, slug)
	if err != nil {
		return nil, WrapError(err)
	}
	if page == nil {
		return nil, PageNotFound(slug)
	}

	// 增加阅读计数
	if err := s.pageService.IncrementViewCount(ctx, page.ID); err != nil {
		// 增加阅读计数失败不影响返回结果
		fmt.Printf("增加页面阅读计数失败: %v\n", err)
	} else {
		page.ViewCount++
	}

	// 转换为响应
	return PageToResponse(page), nil
}

// ListPages 获取自定义页面列表
func (s *service) ListPages(ctx context.Context, params *PageListQueryParams) (*PageListResponse, error) {
	// 设置默认分页参数
	page := 1
	pageSize := 20

	if params != nil {
		if params.Page > 0 {
			page = params.Page
		}
		if params.PageSize > 0 && params.PageSize <= 100 {
			pageSize = params.PageSize
		}
	}

	// 计算偏移量
	offset := (page - 1) * pageSize

	// 查询数据库
	pages, total, err := s.pageService.List(ctx, offset, pageSize, params.Status)
	if err != nil {
		return nil, appErrors.Wrap(err, appErrors.ErrCodeDatabase, "查询页面列表失败")
	}

	// 转换为响应
	return PagesToListResponse(pages, total, page, pageSize), nil
}

// SetPageStatus 设置自定义页面状态
func (s *service) SetPageStatus(ctx context.Context, id uint, req *SetPageStatusRequest, userID uint) (*PageResponse, error) {
	// 获取原始页面信息
	originalPage, err := s.pageService.GetByID(ctx, id)
	if err != nil {
		return nil, WrapError(err)
	}

	// 如果状态没有变化，直接返回
	if originalPage.Status == req.Status {
		return PageToResponse(originalPage), nil
	}

	// 调用领域服务设置页面状态
	updatedPage, err := s.pageService.SetStatus(ctx, id, req.Status)
	if err != nil {
		return nil, WrapError(err)
	}

	// 发布事件
	event := &events.PageStatusSetEvent{
		ID:        updatedPage.ID,
		Status:    updatedPage.Status,
		UpdatedBy: userID,
		UpdatedAt: utils.TimeToJSONTime(updatedPage.UpdatedAt),
	}

	// 异步发布事件
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.PageStatusSetEventType, event))

	// 转换为响应
	return PageToResponse(updatedPage), nil
}
